{%extends 'layout.admin.html'%}
{%block content%}
{% load authfilters %}

<div class="page-header d-print-none">
  <div class="container-xl">
    <div class="row g-2 align-items-center">
      <div class="col">
        <h1 class="page-title">Free Online Image Compressor - Optimize Your Images</h1>
      </div>
      <div class="seo-h1">
        <h2>Compress and Optimize Images Online</h2>
        <h2>Key Features of Our Image Compressor Tool
            <ul>
                <li>Multi-format Support: Compress JPEG, PNG, WebP, and GIF images.</li>
                <li>Quality Control: Adjust compression quality from 1% to 100% for perfect balance.</li>
                <li>Format Conversion: Convert between different image formats seamlessly.</li>
                <li>Batch Processing: Upload and compress multiple images at once.</li>
                <li>Real-time Preview: See before and after comparison instantly.</li>
                <li>100% Client-Side: Your images never leave your browser, ensuring privacy.</li>
            </ul>
        </h2>
        <h2>How to Use This Image Compressor?
            <ul>
                <li>Upload image files by clicking or dragging them to the upload area.</li>
                <li>Adjust compression quality and output format as needed.</li>
                <li>Preview the compressed result with file size comparison.</li>
                <li>Download individual images or batch download as ZIP file.</li>
            </ul>
        </h2>
        <h2>Frequently Asked Questions (FAQs)
            <h3>What image formats are supported?</h3>
            <h3>Will compressing images reduce quality?</h3>
            <h3>Is this image compressor free to use?</h3>
        </h2>
      </div>
    </div>
  </div>
</div>

<style type="text/css">
.image-compress-container {
    min-height: 600px;
}
.upload-area {
    border: 2px dashed #dee2e6;
    border-radius: 0.375rem;
    padding: 3rem 2rem;
    text-align: center;
    background-color: #f8f9fa;
    transition: all 0.3s ease;
    cursor: pointer;
}
.upload-area.dragover {
    border-color: #206bc4;
    background-color: #e7f1ff;
}
.upload-area:hover {
    border-color: #206bc4;
    background-color: #f0f7ff;
}
.quality-slider {
    width: 100%;
    margin: 1rem 0;
}
.format-option {
    margin-right: 1rem;
}
.progress-container {
    margin: 1rem 0;
    display: none;
}
.result-item {
    transition: all 0.2s ease;
}
.result-item:hover {
    background-color: #f8f9fa;
}
.text-sm {
    font-size: 0.875rem;
}
</style>

<div class="page-body">
    <div class="container-xl">
        <div class="row justify-content-center">
            <div class="col-md-8">
                <div class="card">
                    <div class="card-header">
                        <h3 class="card-title">Upload Images</h3>
                    </div>
                    <div class="card-body">
                        <input type="file" id="image-input" multiple accept="image/*" style="display: none;">
                        <div class="upload-area" id="upload-area">
                            <div class="upload-content">
                                <svg xmlns="http://www.w3.org/2000/svg" width="48" height="48" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="icon mb-3 text-muted">
                                    <path d="M14 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V8z"></path>
                                    <polyline points="14,2 14,8 20,8"></polyline>
                                    <circle cx="10" cy="13" r="2"></circle>
                                    <path d="m20 17-1.09-1.09a2 2 0 0 0-2.82 0L10 22"></path>
                                </svg>
                                <h4>Click to upload or drag and drop</h4>
                                <p class="text-muted">JPEG, PNG, WebP, GIF files are supported</p>
                                <p class="text-muted">Maximum file size: 10MB per image</p>
                            </div>
                        </div>
                    </div>
                </div>
            </div>

            <div class="col-md-4">
                <div class="card">
                    <div class="card-header">
                        <h3 class="card-title">Compression Settings</h3>
                    </div>
                    <div class="card-body">
                        <div class="mb-3">
                            <label class="form-label">Quality: <span id="quality-value">80</span>%</label>
                            <input type="range" class="quality-slider" id="quality-slider" min="1" max="100" value="80">
                        </div>

                        <div class="mb-3">
                            <label class="form-label">Output Format</label>
                            <div>
                                <label class="form-check form-check-inline format-option">
                                    <input class="form-check-input" type="radio" name="format" value="original" checked>
                                    <span class="form-check-label">Keep Original</span>
                                </label>
                                <label class="form-check form-check-inline format-option">
                                    <input class="form-check-input" type="radio" name="format" value="jpeg">
                                    <span class="form-check-label">JPEG</span>
                                </label>
                                <label class="form-check form-check-inline format-option">
                                    <input class="form-check-input" type="radio" name="format" value="webp">
                                    <span class="form-check-label">WebP</span>
                                </label>
                                <label class="form-check form-check-inline format-option">
                                    <input class="form-check-input" type="radio" name="format" value="png">
                                    <span class="form-check-label">PNG</span>
                                </label>
                            </div>
                        </div>

                        <div class="mb-3">
                            <label class="form-check">
                                <input class="form-check-input" type="checkbox" id="resize-enabled">
                                <span class="form-check-label">Resize Images</span>
                            </label>
                            <div id="resize-options" class="mt-2" style="display: none;">
                                <div class="row">
                                    <div class="col-6">
                                        <input type="number" class="form-control" id="resize-width" placeholder="Width" min="1" max="4096">
                                    </div>
                                    <div class="col-6">
                                        <input type="number" class="form-control" id="resize-height" placeholder="Height" min="1" max="4096">
                                    </div>
                                </div>
                            </div>
                        </div>

                        <div class="progress-container">
                            <label class="form-label">Processing Progress</label>
                            <div class="progress">
                                <div class="progress-bar" role="progressbar" style="width: 0%"></div>
                            </div>
                        </div>
                    </div>
                </div>
            </div>

            <div class="col-md-12">
                <div class="card" id="results-card" style="display: none;">
                    <div class="card-header">
                        <h3 class="card-title">Compression Results</h3>
                        <div class="card-actions">
                            <button type="button" id="download-all-btn" class="btn btn-success">
                                <svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="icon me-2">
                                    <path d="M21 15v4a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2v-4"></path>
                                    <polyline points="7,10 12,15 17,10"></polyline>
                                    <line x1="12" y1="15" x2="12" y2="3"></line>
                                </svg>
                                Download All as ZIP
                            </button>
                            <button type="button" id="clear-all-btn" class="btn btn-secondary ms-2">
                                <svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="icon me-2">
                                    <line x1="18" y1="6" x2="6" y2="18"></line>
                                    <line x1="6" y1="6" x2="18" y2="18"></line>
                                </svg>
                                Clear All
                            </button>
                        </div>
                    </div>
                    <div class="card-body">
                        <div id="results-container">
                            <!-- Results will be populated here -->
                        </div>
                    </div>
                </div>
            </div>
        </div>
    </div>
</div>

<script src="https://cdn.jsdelivr.net/npm/jszip@3.10.1/dist/jszip.min.js"></script>
<script type='text/javascript'>
$(document).ready(function() {
    let compressedImages = [];

    // Quality slider update
    $('#quality-slider').on('input', function() {
        $('#quality-value').text($(this).val());
    });

    // Resize toggle
    $('#resize-enabled').on('change', function() {
        if ($(this).is(':checked')) {
            $('#resize-options').show();
        } else {
            $('#resize-options').hide();
        }
    });

    // Upload area interactions
    const uploadArea = $('#upload-area');
    const fileInput = $('#image-input');

    uploadArea.on('click', function() {
        fileInput.click();
    });

    uploadArea.on('dragover', function(e) {
        e.preventDefault();
        $(this).addClass('dragover');
    });

    uploadArea.on('dragleave', function(e) {
        e.preventDefault();
        $(this).removeClass('dragover');
    });

    uploadArea.on('drop', function(e) {
        e.preventDefault();
        $(this).removeClass('dragover');
        handleFiles(e.originalEvent.dataTransfer.files);
    });

    fileInput.on('change', function(e) {
        handleFiles(e.target.files);
    });

    function handleFiles(files) {
        const validFiles = [];
        for (let file of files) {
            if (file.type.startsWith('image/') && file.size <= 10 * 1024 * 1024) {
                validFiles.push(file);
            } else {
                alert(`File ${file.name} is either not an image or exceeds 10MB limit.`);
            }
        }

        if (validFiles.length > 0) {
            processFiles(validFiles);
        }
    }

    function processFiles(files) {
        $('.progress-container').show();
        $('#results-card').show();
        $('#results-container').empty();

        let completed = 0;
        const total = files.length;

        files.forEach((file, index) => {
            setTimeout(() => {
                compressImage(file, () => {
                    completed++;
                    const progress = (completed / total) * 100;
                    $('.progress-bar').css('width', progress + '%');
                    if (completed === total) {
                        setTimeout(() => $('.progress-container').hide(), 1000);
                    }
                });
            }, index * 200);
        });
    }

    function compressImage(file, callback) {
        const quality = parseInt($('#quality-slider').val()) / 100;
        const format = $('input[name="format"]:checked').val();
        const resizeEnabled = $('#resize-enabled').is(':checked');
        const resizeWidth = $('#resize-width').val();
        const resizeHeight = $('#resize-height').val();

        const canvas = document.createElement('canvas');
        const ctx = canvas.getContext('2d');
        const img = new Image();

        img.onload = function() {
            let { width, height } = img;

            // Handle resizing
            if (resizeEnabled && (resizeWidth || resizeHeight)) {
                if (resizeWidth && resizeHeight) {
                    width = parseInt(resizeWidth);
                    height = parseInt(resizeHeight);
                } else if (resizeWidth) {
                    width = parseInt(resizeWidth);
                    height = (img.height * width) / img.width;
                } else if (resizeHeight) {
                    height = parseInt(resizeHeight);
                    width = (img.width * height) / img.height;
                }
            }

            canvas.width = width;
            canvas.height = height;
            ctx.drawImage(img, 0, 0, width, height);

            // Determine output format
            let outputFormat = 'image/jpeg';
            let fileExtension = '.jpg';
            if (format === 'original') {
                outputFormat = file.type;
                fileExtension = getFileExtension(file.type);
            } else if (format === 'png') {
                outputFormat = 'image/png';
                fileExtension = '.png';
            } else if (format === 'webp') {
                outputFormat = 'image/webp';
                fileExtension = '.webp';
            }

            // Compress
            canvas.toBlob(function(blob) {
                const compressedData = {
                    originalName: file.name,
                    originalSize: file.size,
                    compressedBlob: blob,
                    compressedSize: blob.size,
                    fileExtension: fileExtension
                };

                compressedImages.push(compressedData);
                displayResult(compressedData);

                if (callback) callback();
            }, outputFormat, quality);
        };

        const reader = new FileReader();
        reader.onload = function(e) {
            img.src = e.target.result;
        };
        reader.readAsDataURL(file);
    }

    function displayResult(data) {
        const reduction = ((data.originalSize - data.compressedSize) / data.originalSize * 100).toFixed(1);
        const compressionClass = reduction > 0 ? 'text-success' : 'text-warning';

        const resultHtml = `
            <div class="result-item mb-3">
                <div class="d-flex justify-content-between align-items-center p-3 border rounded">
                    <div class="flex-grow-1">
                        <h6 class="mb-1">${data.originalName}</h6>
                        <div class="row text-sm">
                            <div class="col-4">
                                <small class="text-muted">Original:</small><br>
                                <span class="fw-bold">${formatBytes(data.originalSize)}</span>
                            </div>
                            <div class="col-4">
                                <small class="text-muted">Compressed:</small><br>
                                <span class="fw-bold">${formatBytes(data.compressedSize)}</span>
                            </div>
                            <div class="col-4">
                                <small class="text-muted">Reduction:</small><br>
                                <span class="fw-bold ${compressionClass}">${reduction}%</span>
                            </div>
                        </div>
                    </div>
                    <div class="ms-3">
                        <button class="btn btn-sm btn-success download-single" data-index="${compressedImages.length - 1}">
                            <svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="icon me-1">
                                <path d="M21 15v4a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2v-4"></path>
                                <polyline points="7,10 12,15 17,10"></polyline>
                                <line x1="12" y1="15" x2="12" y2="3"></line>
                            </svg>
                            Download
                        </button>
                    </div>
                </div>
            </div>
        `;

        $('#results-container').append(resultHtml);
    }

    // Event handlers
    $(document).on('click', '.download-single', function() {
        const index = $(this).data('index');
        downloadSingle(index);
    });

    $('#download-all-btn').on('click', function() {
        downloadAllAsZip();
    });

    $('#clear-all-btn').on('click', function() {
        clearAll();
    });

    function downloadSingle(index) {
        const data = compressedImages[index];
        if (data && data.compressedBlob) {
            const url = URL.createObjectURL(data.compressedBlob);
            const a = document.createElement('a');
            a.href = url;
            a.download = 'compressed_' + data.originalName.replace(/\.[^/.]+$/, "") + data.fileExtension;
            a.click();
            URL.revokeObjectURL(url);
        }
    }

    function downloadAllAsZip() {
        if (compressedImages.length === 0) {
            alert('No compressed images to download.');
            return;
        }

        const zip = new JSZip();
        compressedImages.forEach((data, index) => {
            const fileName = 'compressed_' + data.originalName.replace(/\.[^/.]+$/, "") + data.fileExtension;
            zip.file(fileName, data.compressedBlob);
        });

        zip.generateAsync({type: "blob"}).then(function(content) {
            const url = URL.createObjectURL(content);
            const a = document.createElement('a');
            a.href = url;
            a.download = 'compressed_images.zip';
            a.click();
            URL.revokeObjectURL(url);
        });
    }

    function clearAll() {
        compressedImages = [];
        $('#results-container').empty();
        $('#results-card').hide();
        $('.progress-container').hide();
        $('.progress-bar').css('width', '0%');
    }

    function formatBytes(bytes) {
        if (bytes === 0) return '0 bytes';
        const k = 1024;
        const sizes = ['bytes', 'KB', 'MB', 'GB'];
        const i = Math.floor(Math.log(bytes) / Math.log(k));
        return parseFloat((bytes / Math.pow(k, i)).toFixed(2)) + ' ' + sizes[i];
    }

    function getFileExtension(mimeType) {
        const extensions = {
            'image/jpeg': '.jpg',
            'image/png': '.png',
            'image/webp': '.webp',
            'image/gif': '.gif'
        };
        return extensions[mimeType] || '.jpg';
    }
});
</script>

<script type="application/ld+json">
{
  "@context": "https://schema.org",
  "@type": "SoftwareApplication",
  "name": "Free Online Image Compressor and Optimizer",
  "applicationCategory": "DeveloperApplication",
  "operatingSystem": "Any",
  "offers": {
    "@type": "Offer",
    "price": "0",
    "priceCurrency": "USD"
  },
  "description": "Compress and optimize images online for free. Reduce file size while maintaining quality. Supports JPEG, PNG, WebP, and GIF formats.",
  "keywords": "image compressor, image optimizer, compress images online, reduce image size, image converter"
}
</script>
{%endblock%}
